/*
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *
 *  Authors:
 *  	Albert Marieges Garcia
 *  	Álex Pardo Fernández
 *  	Enric Mayas Márquez
 *  	Juan Carlos Calvo Tejedor
 *  	Marc Gironés Dezsényi
 *  
 *  Contact:
 *  	bcn.tours.android@gmail.com
 *  Webpage:
 *  	bcntours.co.cc
 *
 */

package com.BCNTours.AR.Vista;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationProvider;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import android.widget.Toast;

import com.BCNTours.AR.Utils.ARLocationManager;
import com.BCNTours.AR.Utils.Coordinates;
import com.BCNTours.Maps.Utils.CalcRoute;
import com.google.android.maps.GeoPoint;

/**
 * Activity that shows the camera view, and an arrow indicating the directions to follow to reach the destiny point.
 */
public class ARRoute extends Activity {
	
	//Class attributes
	private CamPreview mPreview;
	private DrawSignal mDraw;
	private DrawArrow mArrow;
	
	
	private SensorManager mySensorManager;
	private ARLocationManager myLocationManager;
	
	private Location myLocation;
	private Coordinates destination;
	private Coordinates nextPoint = new Coordinates(0, 0);
	private float myAzimuth;
	@SuppressWarnings("unused")
	private float myPitch;
	
	private String [] route = null;
	private int posRoute = 0;
	
	
	/** 
	 * Called when the activity is first created. 
	 */
    @Override
	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setWindowOptions();      
        
        //Gets the coordinates of the destination point
        Bundle extras = getIntent().getExtras();
        destination = new Coordinates(0, 0);
        destination.setLt((float)extras.getFloat("latitude"));
        destination.setLn((float)extras.getFloat("longitude"));
       
        //Create our Preview view and set it as the content of our activity.
        mPreview = new CamPreview(getBaseContext());
        mPreview.reconnectCamera();
        Log.i("first", "first creating camera ARRoute");
        setContentView(mPreview); 
        
        //Create the signal marker
        mDraw = new DrawSignal(getApplicationContext());
        addContentView(mDraw, new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
        
        //Draws the arrow marking the direction to follow
        mArrow = new DrawArrow(getApplicationContext(), destination);
        addContentView(mArrow, new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
        
        //Initialization of the location
        initializationLocation();
        
        //Starting sensors
        initializationSensor();
        
        try {
			if(myLocation != null){
				route = new  CalcRoute().getRoute(new GeoPoint((int)(myLocation.getLatitude()*1E6), (int)(myLocation.getLongitude()*1E6)), (new GeoPoint((int)(destination.getLt()*1E6), (int)(destination.getLn()*1E6))));
				String[] lngLat = route[posRoute].split(",");
				nextPoint.setLt(Float.parseFloat(lngLat[1]));
				nextPoint.setLn(Float.parseFloat(lngLat[0]));
				mArrow.setDest(nextPoint);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			Toast.makeText(getApplicationContext(), "You need internet connection...", Toast.LENGTH_LONG).show();
			finish();
			e.printStackTrace();
		}
    }


	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		try {
			Log.i("first", "reconnecting camera ARRoute");
			
			mPreview.reconnectCamera();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		super.onResume();
	}

	
	@Override
	protected void onPause() {
		try {
			mPreview.stopCamera();
			mPreview.releaseCamera();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		super.onPause();
	}

	

	/**
	 * Sets the window options such as the no title option, landscape orientation, etc.
	 */
    private void setWindowOptions(){
    	requestWindowFeature(Window.FEATURE_NO_TITLE);
    	setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
    

    
    /**
     * Initialization of the orientation
     */
    private void initializationSensor(){
        mySensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        List<Sensor> mySensors = mySensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
        
        //If the sensor works
        if(mySensors.size() > 0){
        	mySensorManager.registerListener(mySensorEventListener, mySensors.get(0), SensorManager.SENSOR_DELAY_NORMAL);
        	Toast.makeText(this, "Starting ORIENTATION Sensor", Toast.LENGTH_SHORT).show();
        }
        
        //If the sensor does not work
        else{
        	Toast.makeText(this, "No ORIENTATION Sensor", Toast.LENGTH_LONG).show();
        	finish();	
        }
    }

    /**
     * Initialization of the location
     */
    private void initializationLocation(){
	   
    	myLocationManager = new ARLocationManager(getApplicationContext());
    	myLocationManager.requestUpdates(2000, 10, locationListener);
    	Location location = myLocationManager.getLastLocation();
    	myLocation = location;
		updateARScreen();

    }
    
    
	/**
     * Sensor listener
     */
    private SensorEventListener mySensorEventListener = new SensorEventListener(){

		public void onAccuracyChanged(Sensor sensor, int accuracy) {}

		public void onSensorChanged(SensorEvent event) {
			// TODO Auto-generated method stub
			Log.i("sensor","sensor");
			if(event.sensor.getType() == Sensor.TYPE_ORIENTATION){
				//Update the points of interest buttons with the actual location
				myAzimuth = event.values[0];
				myPitch = event.values[1];
				updateARScreen();
			}
		}
    };
    
   
    
    
    /**
     * Location listener
     */
	private final LocationListener locationListener = new LocationListener() {
		//When changing the location call the method which updates the screen with the new position
		public void onLocationChanged(Location location) {
			myLocation = location;
			if(route == null){
				route = new  CalcRoute().getRoute(new GeoPoint((int)(myLocation.getLatitude()*1E6), (int)(myLocation.getLongitude()*1E6)), (new GeoPoint((int)(destination.getLt()*1E6), (int)(destination.getLn()*1E6))));
				try {
					String[] lngLat = route[posRoute].split(",");
					nextPoint.setLt(Float.parseFloat(lngLat[1]));
					nextPoint.setLn(Float.parseFloat(lngLat[0]));
					mArrow.setDest(nextPoint);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return;
				}
			}
			mDraw.drawSignal(2);
			Coordinates coordinate = new Coordinates(new Float(myLocation.getLatitude()), new Float(myLocation.getLongitude()));
			if(coordinate.getDistance_km(nextPoint) < 0.05){ //If the distance is less than 50m
				posRoute ++;
				if(route.length > posRoute){
					String[] lngLat = route[posRoute].split(",");
		        	nextPoint.setLt(Float.parseFloat(lngLat[1]));
		        	nextPoint.setLn(Float.parseFloat(lngLat[0]));
		        	mArrow.setDest(nextPoint);
				} else{
					Toast.makeText(getApplicationContext(), "FI", Toast.LENGTH_LONG);
					
					Toast.makeText(getApplicationContext(), "Now will close this window", Toast.LENGTH_LONG);
					
					finish();
				}
			}
			mArrow.setCurrentPosition(coordinate, myAzimuth);
			
		}
		
		//When position is not found
		public void onProviderDisabled(String provider){
			Toast.makeText(getApplicationContext(), "No location found", Toast.LENGTH_LONG).show();
			mDraw.drawSignal(0);
			
			finish();
		}
		public void onProviderEnabled(String provider){ }
		public void onStatusChanged(String provider, int status, Bundle extras){
			if(status == LocationProvider.TEMPORARILY_UNAVAILABLE){
				mDraw.drawSignal(1);
			}else if(status == LocationProvider.AVAILABLE){
				mDraw.drawSignal(2);
			}else{
				mDraw.drawSignal(0);
			}
		}
	};
	
	/**
	 * The method which updates the list of the points of interest on the camera screen and the radar.
	 * @param location keep the actual location
	 * @param azimuth Angle between the magnetic north direction and the Y axis, around the Z axis (0 to 359).
	 * @param pitch Rotation around X axis (-180 to 180)
	 */
	private void updateARScreen() {
		//When the location is ok
		try {
			//Update the points of interest buttons with the actual location
			if(myLocation != null){
				Coordinates coordinate = new Coordinates(new Float(myLocation.getLatitude()), new Float(myLocation.getLongitude()));
				mArrow.setCurrentPosition(coordinate, myAzimuth);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Log.e("no loc", "-----------> Couldn't find the location!");
		}
	}

	
	@Override
	public void onBackPressed() {
		super.onBackPressed();
		myLocationManager.removeUpdates(locationListener);
		mySensorManager.unregisterListener(mySensorEventListener);
		Log.i("rel", "releasing camera ARRoute");
		mPreview.stopCamera();
		mPreview.releaseCamera();
		ARRoute.this.finish();
	}
}

